#include "InferenceModel.h"

InferenceModel::InferenceModel(){
    compressedStatements = true;
    optimizedQueries = false;
}

InferenceModel::~InferenceModel(){

}

void InferenceModel::setCompressedSourceStatements( bool b )
{
    compressedStatements = b;
}

void InferenceModel::setOptimizedQueriesEnabled( bool b )
{
    optimizedQueries = b;
}

void InferenceModel::addRule( FwdRule rule )
{
    rules.append( rule );
}

void InferenceModel::setRules( QList<FwdRule> ruless )
{
    rules = ruless;
}

ErrorCode InferenceModel::addStatement( Statement statement )
{
	//toDO
	ErrorCode error=ErrorNone;
//    Error::ErrorCode error = FilterModel::addStatement( statement );
//    if ( error == Error::ErrorNone ) {
//        // FIXME: error handling for the inference itself
//        if( inferStatement( statement, true ) ) {
//            emit statementsAdded();
//        }
//    }
    return error;
}

void InferenceModel::performInference()
{
    for ( QList<FwdRule>::iterator it = rules.begin();
          it != rules.end(); ++it ) {
    	int counter;
        // reset the binding statement, we want to infer it all
        FwdRule rule = *it;
        Statement state;
        rule.bindToStatement(state);
        counter=inferRule( rule, true );
        std::cout << "After inference, we add " << counter << " Statements into the db" << std::endl;
    }
}


int InferenceModel::inferStatement( Statement statement, bool recurse )
{
    int cnt = 0;
    for ( QList<FwdRule>::iterator it = rules.begin();
          it != rules.end(); ++it ) {
        FwdRule& rule = *it;
//        if( rule.match( statement) ) {
//            rule.bindToStatement( statement );
            cnt += inferRule( rule, recurse );
//        }
    }
    return cnt;
}

int InferenceModel::inferRule( FwdRule& rule, bool recurse )
{
    QString q = rule.createSparqlQuery( optimizedQueries );
    if ( q.isEmpty() ) {
        return 0;
    }
    else {
//         qDebug() << "Applying rule:" << rule;
         qDebug() << "Rule query:" << q;

        int inferedStatementsCount = 0;

        // remember the infered statements to recurse later on
        QList<Statement> inferedStatements;  	//这里装载着被infer出来的statement

        // cache the bindings since we work recursively and Soprano would block in the addStatement calls otherwise
//        QList<BindingSet> bindings = parentModel()->executeQuery( q, Query::QueryLanguageSparql ).allBindings();  //返回所有待绑定的元素

        //在此处实现查找功能  //在此处执行查询，并且将查询的结构装载在bindings中
        QList<NTuple> bindings;
        std::vector<NTuple> partialResult;
        std::string queryOption="query";
	    std::string dbName="semantic_node_All.db";
	    std::string result;
	    std::string query_cmd=q.toStdString();

	    for(int i=0;i<1;i++){		//加入循环，加速对数据库的关闭
	    	RdfStore query(queryOption,dbName);
	    	query.exec_query(query_cmd);
	    	partialResult=query.partialResult;
	    }

	    for(int i=0;i<partialResult.size();i++){
	    	bindings.push_back(partialResult.at(i));
	    	std::cout << partialResult.at(i).toString() << std::endl;
	    }
	    //在此处实现将所有的答案存储在bindings

	    RdfStore query(queryOption,dbName);
	    for ( QList<NTuple>::iterator it = bindings.begin(); it != bindings.end(); ++it ) {
	    	NTuple binding =*it;

//	    	std::cout << "Begin to handler the bindings: " << it->toString() << std::endl;
	    	Statement inferedStatement = rule.bindEffect( binding ); //对Effect进行操作，意思是产生Effect应该产生的语义

            // we only add infered statements if they are not already present (in any named graph, aka. context)
//	    	std::cout << inferedStatement.toString() << std::endl;
	    	if (true){   //FIXME 补充 inferedStatement.isValid()的逻辑
	    		if(!query.containsAnyStatement(inferedStatement)){
	    			std::cout << "inferedStatement Add!!!" << std::endl;
	    			++inferedStatementsCount;
	    			query.addStatement(inferedStatement);
	    			inferedStatement_toSend.push_back(inferedStatement);
	    		}

	    	}


	    }

        // We only recurse after finishing the loop since this will reset the bound statement
        // in the rule which leads to a lot of confusion
	    std::cout << " The recurse is: " << recurse << std::endl;
        if ( recurse && inferedStatementsCount ) {
            foreach( const Statement& s, inferedStatements ) {  //遍历所有的inferdStatements,把，infer出来的statement装到S去。作为日后的新的infer的依据。
                inferedStatementsCount += inferStatement( s, true );
            }
        }

        return inferedStatementsCount;
    }
}


std::vector<Statement> InferenceModel::getInferedStatement(){
	return inferedStatement_toSend;
}
